#pragma once
#include <boost/array.hpp>
#include "ImportExport.hpp"

namespace he
{
	//! Terrain tile class.
	class Tile
	{
		// Constants
	private:
		static unsigned char const VERTEX_SIZE = 4;
		static unsigned char const TRIANGLE_COUNT = 2;

		// Typedefs
	public:
		typedef boost::array<char, VERTEX_SIZE> Height_t;
		typedef boost::array<Ogre::Vector3 *, VERTEX_SIZE> VectorPtrArray_t;
		typedef boost::array<Ogre::Vector3, TRIANGLE_COUNT> NormalArray_t;
		//! Array of terrain types.
		typedef boost::array<unsigned short *, VERTEX_SIZE> TerrainTypeArray_t;

		// Attributes
	private:
		//! X position.
		unsigned short const m_X;
		//! Y position.
		unsigned short const m_Y;
		//! Vertices.
		VectorPtrArray_t m_Vertices;
		//! Normal vector of 2 triangles.
		NormalArray_t m_Normals;
		//! Type variant index.
		/*!
			This index is used to use different terrain type variant.
		*/
		unsigned short m_TerrainTypeVariantIndex;
		//! Each vertex's terrain type (grass, mud, ...). Maximum of 2 different type per tile could be specified which will be blended together.
		TerrainTypeArray_t m_TerrainTypeArray;

		// Operations
	public:
		//! Get the X position.
		unsigned short get_x() const;
		//! Get the Y position.
		unsigned short get_y() const;
		//! Get the n-th vertex.
		HE_ENGINE_API Ogre::Vector3 *get_vertex(unsigned short Vertex) const;
		//! Get vertex normal.
		HE_ENGINE_API Ogre::Vector3 const &get_normal(unsigned short Index) const;
		//! Set height of particular vertex.
		HE_ENGINE_API void set_deep(unsigned short Vertex, float Height, bool RecalculateNormals = false, bool Absolute = true);
		//! Set normals.
		HE_ENGINE_API void set_normals(Ogre::Vector3 const &Normal0, Ogre::Vector3 const &Normal1);
		//! Set vertices.
		HE_ENGINE_API void set_vertices(Ogre::Vector3 *pV0, Ogre::Vector3 *pV1, Ogre::Vector3 *pV2, Ogre::Vector3 *pV3);
		//! Recalculate face normals.
		HE_ENGINE_API void recalculate_normals();
		//! Get tile width.
		static unsigned short get_tile_width();
		//! Get tile height.
		static unsigned short get_tile_height();
		//! Set the tile terrain variant index.
		void set_terrain_index(unsigned short Index);
		//! Get tile terrain variant index.
		unsigned short get_terrain_type_variant_index() const;
		//! Get terrain type for vertex.
		HE_ENGINE_API unsigned short &get_terrain_type(unsigned short Vertex) const;
		//! Set the terrain types for each vertex.
		HE_ENGINE_API void set_terrain_type_for_vertex(unsigned short Vertex, unsigned short *Type);
		
		// Construction/Destruction
	public:
		HE_ENGINE_API Tile(unsigned short X, unsigned short Y);
	};

	inline unsigned short Tile::get_x() const
	{
		return m_X;
	}

	inline unsigned short Tile::get_y() const
	{
		return m_Y;
	}

	inline unsigned short Tile::get_tile_width()
	{
		return 2;
	}

	inline unsigned short Tile::get_tile_height()
	{
		return 2;
	}

	inline void Tile::set_terrain_index(unsigned short Index)
	{
		m_TerrainTypeVariantIndex = Index;
	}

	inline unsigned short Tile::get_terrain_type_variant_index() const
	{
		return m_TerrainTypeVariantIndex;
	}
}

